#-*- coding:utf-8 -*-
import zmq
import time
import configparser
import os
import re
import json
import shutil
import zipfile
import threading
import traceback
from socket import socket, AF_INET, SOCK_STREAM
from datetime import datetime


class client_cu(object):
    def __init__(self):
        self.context = zmq.Context()
        self.config_file = 'config.ini'
        self.config = configparser.ConfigParser()
        self.config.read(self.config_file)
        self.topic_name = 'zcell02'
        self.host_ip = self.config.get('zcells', 'client_ip')

    def pub_zcell(self):
        while True:
            print('更新进程已经启动')
            server_ip = self.config.get('zcells', 'server_ip')
            pub_port = self.config.get('zcells', 'up_sub_port')
            pub_socket = self.context.socket(zmq.SUB)
            pub_socket.connect("tcp://%s:%s" % (server_ip, pub_port))
            pub_socket.setsockopt_string(zmq.SUBSCRIBE, self.topic_name)
            zcell_data1 = pub_socket.recv_string()
            zcell_data2 = zcell_data1.split('|')
            pub_socket.close()
            if len(zcell_data2) == 2:
                print('全部更新')
                zcell_directory = self.analysis_file(zcell_data2[1])
                print(zcell_directory)
                self.start_socket(zcell_directory, 1)
            elif len(zcell_data2) == 3:
                print('指定更新')
                self.req_zcell('one')
                print(zcell_data2)
                self.start_socket(zcell_data2, 2)
            else:
                print('获取的数据异常')

    def analysis_file(self, zcell_rules):
        updata_rulues = eval(zcell_rules)
        print(updata_rulues)
        w = self.config.get('zcells', 'source_file')
        zcell_zip = []
        zcell_zip_file = {}
        return_zcell_json = {}
        a = [x for x in os.listdir(w) if os.path.isdir(w + '/' + x)]
        for n in updata_rulues:
            zip_name = ""
            zcell_file = []
            for i in a:
                if n.search(i):
                    f = w + '\\' + i
                    zcell_file.append(f)
                    zip_name = i[:-5] + '.zip'
                    if zip_name not in zcell_zip:
                        zcell_zip.append(zip_name)
                else:
                    pass
            if zip_name != '':
                zcell_zip_file[zip_name] = zcell_file
        print(zcell_zip_file)
        return_zcell_json['id'] = self.topic_name
        return_zcell_json['module'] = zcell_zip
        return_zcell_json['number'] = len(zcell_zip)
        return_zcell_json['ip'] = self.host_ip
        self.req_zcell(json.dumps(return_zcell_json))
        return zcell_zip_file

    def req_zcell(self, return_zcell_json):
        server_ip = self.config.get('zcells', 'server_ip')
        req_port = self.config.get('zcells', 'up_req_port')
        req_socket = self.context.socket(zmq.REQ)
        req_socket.connect("tcp://%s:%s" % (server_ip, req_port))
        req_socket.send_string(return_zcell_json)
        msg = req_socket.recv_string()
        print(msg)
        req_socket.close()

    def move_zip(self, zcell_directory, zip_directory, zip_name):
        directory = zcell_directory[zip_name]
        for i in directory:
            exe_name = i.split('\\').pop()
            exe_file = i
            exe_file_zip = os.path.join(i, zip_name)
            shutil.copy(src=zip_directory, dst=exe_file_zip)
            print('==============================')
            print(exe_name, exe_file, exe_file_zip)
            self.Unpack_zip(exe_name, exe_file, exe_file_zip)
        os.remove(zip_directory)

    def Unpack_zip(self, exe_name, exe_file, exe_file_zip):
        date = datetime.now().strftime("%Y%m%d%H%M")
        back_name1 = exe_file_zip.split('\\').pop()
        back_name2 = date + '_' + back_name1
        back_file = os.path.join(exe_file, back_name2)
        print('=========================')
        print(back_name2, back_file)
        # try:
        #     command = 'taskkill /F /IM %s' % exe_name
        #     os.system(command)
        #     print("成功关闭相关进程：%s" % exe_name)
        # except:
        #     print("进程未关闭成功：%s" % exe_name)

        zf = zipfile.ZipFile(exe_file_zip, 'r')
        zf.extractall(exe_file)
        zf.close()
        lists = os.listdir(exe_file)
        for item2 in lists:
            if item2.endswith('exe'):
                old_exe_name = os.path.join(exe_file, item2)
                new_exe_name = os.path.join(exe_file, exe_name + '.exe')
                shutil.move(old_exe_name, new_exe_name)
                print("修改执行文件名称：%s" % exe_name)
        shutil.move(exe_file_zip, back_file)
        # return

    def start_socket(self, zcell_directory, num):
        connection = socket(AF_INET, SOCK_STREAM)
        connection.connect(('localhost', 20000))
        connection.send(b'zcell02')
        zip_file1 = self.config.get('zcells', 'source_file')
        while True:
            module_line = connection.recv(num)
            print(module_line)
            if module_line == b'1':
                break
            module_name1 = connection.recv(int(module_line.decode('utf-8')))
            module_name2 = module_name1.decode('utf-8').split('|')
            print(module_name2)
            if len(module_name2) == 1:
                while True:
                    data = connection.recv(20480)
                    zip_file2 = os.path.join(zip_file1, module_name2[0])
                    if data == b'next':
                        print("%s数据包接收完成，等待......" % module_name2[0])
                        break
                    with open(zip_file2, 'ab') as f:
                        f.write(data)
                    f.close()
                print(module_name2)
                self.move_zip(zcell_directory, zip_file2, module_name2[0])
            elif len(module_name2) == 2:
                while True:
                    data = connection.recv(20480)
                    zip_file2 = os.path.join(zip_file1, module_name2[1])
                    zip_file3 = os.path.join(zip_file2, module_name2[0])
                    if data == b'next':
                        print("%s数据包接收完成，等待......" % module_name2[0])
                        break
                    with open(zip_file3, 'ab') as f:
                        f.write(data)
                    f.close()
                self.Unpack_zip(module_name2[1], zip_file2, zip_file3)
        print('更新完成')
        connection.close()

    def pub_zcell_d(self):
        while True:
            print('部署进程已经启动')
            server_ip = self.config.get('deployment', 'server_ip')
            pub_port = self.config.get('deployment', 'up_sub_port')
            req_port = self.config.get('deployment', 'up_req_port')
            pub_socket = self.context.socket(zmq.SUB)
            pub_socket.connect("tcp://%s:%s" % (server_ip, pub_port))
            pub_socket.setsockopt_string(zmq.SUBSCRIBE, self.topic_name)
            zcell_data1 = pub_socket.recv_string().split('|')
            zcell_data2 = eval(zcell_data1[1])
            print(zcell_data2)
            socket_port = int(self.config.get('deployment', 'socket_port'))
            connection = socket(AF_INET, SOCK_STREAM)
            connection.connect((server_ip, socket_port))
            status = self.socket_zip_d(connection, zcell_data2)
            pub_socket.close()
            connection.close()
            req_socket = self.context.socket(zmq.REQ)
            req_socket.connect("tcp://%s:%s" % (server_ip, req_port))
            req_socket.send_string(status)
            time.sleep(20)

    def uzip_d(self, zcell_name, page_file):
        zcell_file = zcell_name.split('.')[0]
        zcell_directory = os.path.join(page_file, zcell_file)
        zcell_old_zip = os.path.join(page_file, zcell_name)
        zcell_new_zip = os.path.join(zcell_directory, zcell_name)
        date = datetime.now().strftime('%Y%m%d%H%M')
        try:
            os.mkdir(zcell_directory)
            shutil.move(zcell_old_zip, zcell_new_zip)
            zf = zipfile.ZipFile(zcell_new_zip, 'r')
            zf.extractall(zcell_directory)
            zf.close()
            back_file = os.path.join(zcell_directory, date + '_' + zcell_name)
            shutil.move(zcell_new_zip, back_file)
            print('%s 解压部署完成' % zcell_file)
        except FileExistsError as e:
            print('filename名称重复: %s' % e)

    def socket_zip_d(self, connection, zcell_list):
        page_file = self.config.get('deployment', 'source_file')
        try:
            for i in zcell_list:
                zip_name = i + '.zip'
                page_d1 = os.path.join(page_file, i)
                page_d2 = os.path.join(page_file, zip_name)
                num = str(len(zip_name))
                connection.send(bytes(num, encoding="utf8"))
                connection.send(bytes(zip_name, encoding="utf8"))
                print('开始接收 %s' % zip_name)
                while True:
                    data = connection.recv(20480)
                    if data == b'':
                        exit(1)
                    if data == b'end':
                        break
                    with open(page_d2, 'ab') as f:
                        f.write(data)
                    f.close()
                print('%s 接受完成' % i)
                self.uzip_d(zip_name, page_file)

            connection.send(b'de')
            connection.close()
            status = str(zcell_list)

        except:
            traceback.print_exc()
            status = str(["error"])
        return status

    def main_body(self):
        t1 = threading.Thread(target=self.pub_zcell)
        t2 = threading.Thread(target=self.pub_zcell_d)
        t1.start()
        t2.start()

if __name__ == '__main__':
    a = client_cu()
    a.main_body()
